package com.hcc.gateway.app.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import com.hcc.gateway.domain.enums.ApiParamMappingTypeEnum;
import com.hcc.gateway.domain.enums.ApiParamTypeEnum;
import com.hcc.gateway.domain.vo.ApiParamMappingVo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * ParamConverUtils
 *
 * @author shengjun.hu
 * @date 2022/1/19
 */
public class ParamConvertUtils {

    private static final List<String> BASIC_TYPE = Arrays.asList(ApiParamTypeEnum.Bool.getCode(), ApiParamTypeEnum.Number.getCode(), ApiParamTypeEnum.Str.getCode());

    private ParamConvertUtils() {}

    public static boolean hasParamMapping(ApiParamMappingVo apiParamMappingVo) {
        return apiParamMappingVo != null && CollectionUtil.isNotEmpty(apiParamMappingVo.getChildren());
    }


    private static boolean isArrayParam(Object value, ApiParamMappingVo paramMapping) {
        return ApiParamTypeEnum.Arr.getCode().equals(paramMapping.getParamType());
    }

    private static boolean isObjType(Object value, ApiParamMappingVo paramMapping) {
        return ApiParamTypeEnum.Obj.getCode().equals(paramMapping.getParamType());
    }

    private static boolean isBasicType(Object value, ApiParamMappingVo paramMapping) {
        return BASIC_TYPE.contains(paramMapping.getParamType());
    }

    @SuppressWarnings("unchecked")
    public static Map<String, Object> convertParam(Map<String, Object> paramMap, List<ApiParamMappingVo> paramMappings) {
        Map<String, Object> resultMap = new TreeMap<>();
        if (MapUtil.isEmpty(paramMap)) {
            return resultMap;
        }
        if (CollectionUtil.isEmpty(paramMappings)) {
            return paramMap;
        }
        for (ApiParamMappingVo paramMapping : paramMappings) {
            String paramKey;
            if (ApiParamMappingTypeEnum.REQ.name().equals(paramMapping.getType())) {
                paramKey = paramMapping.getTargetName();
            } else if (ApiParamMappingTypeEnum.RESP.name().equals(paramMapping.getType())) {
                paramKey = paramMapping.getOriginalName();
            } else {
                throw new IllegalArgumentException(String.format("不支持的类型：[%s]", paramMapping.getType()));
            }
            String resultKey;
            if (ApiParamMappingTypeEnum.REQ.name().equals(paramMapping.getType())) {
                resultKey = paramMapping.getOriginalName();
            } else if (ApiParamMappingTypeEnum.RESP.name().equals(paramMapping.getType())) {
                resultKey = paramMapping.getTargetName();
            } else {
                throw new IllegalArgumentException(String.format("不支持的类型：[%s]", paramMapping.getType()));
            }

            Object value = paramMap.get(paramKey);
            if (paramMapping.getRequired() && value == null) {
                throw new IllegalArgumentException(String.format("参数：[%s]为必填参数！", paramKey));
            }
            if (value == null) {
                continue;
            }

            if (isArrayParam(value, paramMapping)) {
                // 没有子节点说明该数组中为基本类型
                if (CollectionUtil.isEmpty(paramMapping.getChildren())) {
                    resultMap.put(resultKey, value);
                    continue;
                }
                resultMap.put(resultKey, convertParamArr((List<Object>) value, paramMapping.getChildren()));
                continue;
            }
            if (isObjType(value, paramMapping)) {
                // 没有子节点，此处直接取值
                if (CollectionUtil.isEmpty(paramMapping.getChildren())) {
                    resultMap.put(resultKey, value);
                    continue;
                }
                resultMap.put(resultKey, convertParam((Map<String, Object>) value, paramMapping.getChildren()));
                continue;
            }
            if (isBasicType(value, paramMapping)) {
                resultMap.put(resultKey, value);
                continue;
            }
            throw new IllegalArgumentException(String.format("参数：[%s]类型未知！", paramKey));
        }

        return resultMap;
    }

    @SuppressWarnings("unchecked")
    public static List<Object> convertParamArr(List<Object> paramArr, List<ApiParamMappingVo> paramMappings) {
        if (CollectionUtil.isEmpty(paramMappings)) {
            return paramArr;
        }

        List<Object> resultMaps = new ArrayList<>();
        for (Object param : paramArr) {
            Map<String, Object> resultMap = convertParam((Map<String, Object>) param, paramMappings);
            resultMaps.add(resultMap);
        }

        return resultMaps;
    }

}
